/**
 * 
 */
package ca.tatham.triplipse.views.tree;

import org.eclipse.jface.viewers.DecoratingLabelProvider;
import org.eclipse.jface.viewers.IColorDecorator;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITreeSelection;
import org.eclipse.jface.viewers.StructuredViewer;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;
import org.openrdf.model.Value;

import ca.tatham.triplipse.Activator;
import ca.tatham.triplipse.views.IRdfStatementLabelProvider;
import ca.tatham.triplipse.views.RdfStatementLabelProvider;

/**
 * Provides delegation to a decorator and a RdfStatementLabelProvider. The image
 * provider will give the appropriate symbol for each node in the tree for
 * Subject, Predicate and Object. In addition, it checks if a recursive was
 * found and indicates that to the user as well.
 * 
 * @author BenTatham
 */
class TreeRdfStatementDecoratingLabelProvider extends DecoratingLabelProvider
		implements IRdfStatementLabelProvider {

	TreeRdfStatementDecoratingLabelProvider(StructuredViewer viewer) {
		super(new TreeRdfStatementLabelProvider(), new TreeRdfStatementLabelDecorator(
				viewer));
	}

	public boolean togglePrefix() {
		return ((TreeRdfStatementLabelProvider) getLabelProvider()).togglePrefix();
	}

	public boolean isPrefixing() {
		return ((TreeRdfStatementLabelProvider) getLabelProvider()).isPrefixing();
	}

}

class TreeRdfStatementLabelDecorator implements ILabelDecorator, IColorDecorator {

	private final StructuredViewer m_viewer;

	public TreeRdfStatementLabelDecorator(StructuredViewer viewer) {
		m_viewer = viewer;
	}

	public Color decorateBackground(Object element) {
		if (isSelected(element)) {
			return new Color(Display.getCurrent(), 0, 255, 255);
		}
		return null;
	}

	private boolean isSelected(Object element) {
		if (element != null) {
			Object selected = ((ITreeSelection) m_viewer.getSelection())
					.getFirstElement();
			if (selected != null) {
				Value selectedValue = getRdfValue(selected);
				Value elementValue = getRdfValue(element);
				if (selectedValue.equals(elementValue)) {
					return true;
				}
			}
		}
		return false;

	}

	private Value getRdfValue(Object object) {
		Value selectedValue = ((TreeObject) object).getName();
		return selectedValue;
	}

	public Color decorateForeground(@SuppressWarnings("unused")
	Object element) {
		return null;
	}

	public Image decorateImage(Image image, Object element) {
		if (element instanceof TreeParent && ((TreeParent) element).isCycle()) {
			// TODO decorate the image with the cycle image, instead of
			// replacing it
		}
		return image;
	}

	public String decorateText(String text, @SuppressWarnings("unused")
	Object element) {
		return text;
	}

	public void addListener(@SuppressWarnings("unused")
	ILabelProviderListener listener) {
		// do nothing
	}

	public void removeListener(@SuppressWarnings("unused")
	ILabelProviderListener listener) {
		// do nothing
	}

	public void dispose() {
		// do nothing

	}

	public boolean isLabelProperty(@SuppressWarnings("unused")
	Object element, @SuppressWarnings("unused")
	String property) {
		return false;
	}

}

class TreeRdfStatementLabelProvider extends RdfStatementLabelProvider implements
		IFontProvider {

	private static final String ICON_SUBJECT = "/icons/subject.gif";
	private static final String ICON_PREDICATE = "/icons/predicate.gif";
	private static final String ICON_OBJECT_LEAF = "/icons/object_leaf.gif";
	private static final String ICON_OBJECT_PARENT = "/icons/object_parent.gif";
	private static final String ICON_RECURSIVE = "/icons/recursive.gif";

	public String getText(Object obj) {
		String string = obj.toString();
		if (((TreeObject) obj).getNodeType() == NodeType.OBJECT_LITERAL) {
			return getLiteralText(string);
		}
		return getResourceText(string);
	}

	public Image getImage(Object obj) {

		if (obj instanceof TreeParent && ((TreeParent) obj).isCycle()) {
			return Activator.getImageDescriptor(ICON_RECURSIVE).createImage();
		}

		switch (((TreeObject) obj).getNodeType()) {
		case INVISIBLE:
			return null;
		case SUBJECT:
			return Activator.getImageDescriptor(ICON_SUBJECT).createImage();
		case PREDICATE:
			return Activator.getImageDescriptor(ICON_PREDICATE).createImage();
		case OBJECT_LITERAL:
			return Activator.getImageDescriptor(ICON_OBJECT_LEAF).createImage();
		case OBJECT_REF_LEAF:
			return Activator.getImageDescriptor(ICON_OBJECT_LEAF).createImage();
		case OBJECT_REF_PARENT:
			return Activator.getImageDescriptor(ICON_OBJECT_PARENT)
					.createImage();
		}
		return null;
	}

	public Font getFont(Object element) {
		if (element instanceof TreeParent) {
			if (((TreeParent) element).getNodeType().equals(NodeType.PREDICATE)) {
				// TODO get the current font and make it italics
			}
		}
		return null;
	}

}
